SharedWorker跨Tab通信测试
完成 useWorker composable的封装后,需要进行端到端测试验证跨Tab消息传递功能。
测试用例设计
两个页面(index和login)之间的消息通信:
| 测试场景 | 发送方 | 接收方 | 方法 |
|---|---|---|---|
| 点对点消息 | index → login | login | emit('/login', data) |
| 点对点消息 | login → index | index | emit('/index', data) |
| 广播消息 | login → 所有 | index + 其他 | broadcast(data) |
页面端代码
// index.vue
const { on, emit, routeIds } = useWorker()
// 监听消息
on('message', (data) => {
console.log('index page receive:', data)
})
// 发送消息到login页面
const handleClick = () => {
emit('/login', 'hello from page index')
}
typescript
// login.vue
const { on, emit, broadcast } = useWorker()
on('message', (data) => {
console.log('log page received:', data)
})
const handleClick = () => {
emit('/index', 'message from login page')
// 或者使用广播
// broadcast('broadcast from login page')
}
typescript
SharedWorker调试方法
SharedWorker运行在独立线程中,不能通过普通DevTools的Console查看日志。调试方法:
- Chrome浏览器地址栏输入
chrome://inspect - 左侧选择 "Shared Workers"
- 找到对应的Worker,点击 "inspect"
- 在打开的独立DevTools窗口中查看日志
消息去重问题
Vite开发模式下热更新不会销毁SharedWorker实例,导致 connections 和 nextId 持续增长,消息被重复触发多次。
解决方案:在组件卸载时通过 off 方法解除事件绑定:
// useWorker.ts
onUnmounted(() => {
events.forEach(([eventName, handler]) => {
off(eventName, handler)
})
})
typescript
路由ID映射(routeIds)
SharedWorker维护了一个 routeIds 映射表,结构为 { id: routePath }:
[
{ id: 0, route: '/index' },
{ id: 1, route: '/login' },
{ id: 2, route: '/login' }, // 同一路由可能有多个Tab
]
text
用途:当多个Tab打开同一路由时(如多个login页面),向该路由发送消息会同时到达所有Tab。
// routeIds是响应式的,可以直接在模板中使用
const { routeIds } = useWorker()
console.log(routeIds.value)
// [{ id: 0, route: '/index' }, { id: 1, route: '/login' }]
typescript
Tab关闭时的清理
页面关闭时需要通知SharedWorker清理对应的连接:
// 页面关闭前发送close事件
window.addEventListener('beforeunload', () => {
port.postMessage({ type: 'close' })
})
// 组件卸载时移除事件监听
onUnmounted(() => {
window.removeEventListener('beforeunload', handler)
})
typescript
watch监听消息
除了 on 方法监听外,还可以使用Vue的 watch 监听响应式的 message 对象:
const { message } = useWorker()
watch(message, (newMessage) => {
console.log('new message:', newMessage)
})
typescript
这种写法更符合Vue的响应式编程习惯,适合在模板中直接绑定消息数据。
↑